import tkinter as tk
from tkinter import ttk, messagebox
import os
import re
import binascii

class ConfigEditor:
    def __init__(self, root):
        self.root = root
        self.root.title("《仙剑奇侠传四》高清配置程序")
        self.root.geometry("380x400")
        self.root.resizable(False, False)
        
        self.config_path = "config.cfg"
        # 保存原始文件数据
        self.original_data = b''
        
        # 默认值
        self.fullscreen_var = tk.IntVar(value=0)
        self.widescreen_var = tk.IntVar(value=0)
        self.width_var = tk.IntVar(value=800)
        self.height_var = tk.IntVar(value=600)
        self.sync_var = tk.IntVar(value=1)
        
        # 创建分辨率选项列表
        self.resolution_list = [
            "800 × 600",
            "1024 × 768",
            "1280 × 720",
            "1366 × 768",
            "1600 × 900",
            "1920 × 1080",
            "2560 × 1440",
            "3440 × 1440",
            "3840 × 2160",
            "5120 × 2160"
        ]
        
        self.create_widgets()
        self.load_config()
    
    def create_widgets(self):
        # 创建选项卡
        notebook = ttk.Notebook(self.root)
        notebook.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
        
        # 游戏设置选项卡
        game_settings_tab = ttk.Frame(notebook)
        notebook.add(game_settings_tab, text="游戏设置")
        
        # 系统信息选项卡
        system_info_tab = ttk.Frame(notebook)
        notebook.add(system_info_tab, text="系统信息")
        
        # === 游戏设置选项卡内容 ===
        
        # 分辨率设置区域
        res_frame = ttk.LabelFrame(game_settings_tab, text="分辨率")
        res_frame.pack(fill=tk.X, padx=8, pady=5)
        
        # 分辨率下拉框
        self.resolution_var = tk.StringVar(value="800 × 600")
        
        res_combo_frame = ttk.Frame(res_frame)
        res_combo_frame.pack(fill=tk.X, padx=0, pady=0)
        self.res_combo = ttk.Combobox(res_combo_frame, textvariable=self.resolution_var, values=self.resolution_list, width=18)
        self.res_combo.pack(side=tk.LEFT, padx=2, pady=0)
        self.res_combo.bind("<<ComboboxSelected>>", self.on_resolution_select)
        
        # 手动输入分辨率
        ttk.Label(res_combo_frame, text="宽:").pack(side=tk.LEFT, padx=2)
        self.width_entry = ttk.Entry(res_combo_frame, textvariable=self.width_var, width=5)
        self.width_entry.pack(side=tk.LEFT, padx=1)
        ttk.Label(res_combo_frame, text="高:").pack(side=tk.LEFT, padx=2)
        self.height_entry = ttk.Entry(res_combo_frame, textvariable=self.height_var, width=5)
        self.height_entry.pack(side=tk.LEFT, padx=1)
        self.width_entry.bind('<KeyRelease>', self.on_custom_resolution)
        self.height_entry.bind('<KeyRelease>', self.on_custom_resolution)
        
        # 显示模式设置区域
        display_frame = ttk.LabelFrame(game_settings_tab, text="显示模式")
        display_frame.pack(fill=tk.X, padx=8, pady=5)
        
        # 全屏/窗口化单选按钮
        windowed_radio = ttk.Radiobutton(display_frame, text="窗口化", variable=self.fullscreen_var, value=0)
        windowed_radio.pack(side=tk.LEFT, padx=10, pady=8)
        
        fullscreen_radio = ttk.Radiobutton(display_frame, text="全屏", variable=self.fullscreen_var, value=1)
        fullscreen_radio.pack(side=tk.LEFT, padx=10, pady=8)
        
        # 是否宽屏设置区域
        widescreen_frame = ttk.LabelFrame(game_settings_tab, text="宽屏模式")
        widescreen_frame.pack(fill=tk.X, padx=8, pady=5)
        widescreen_check = ttk.Checkbutton(widescreen_frame, text="启用宽屏（16:9）", variable=self.widescreen_var)
        widescreen_check.pack(anchor=tk.W, padx=10, pady=5)
        
        # 垂直同步设置区域
        sync_frame = ttk.LabelFrame(game_settings_tab, text="垂直同步")
        sync_frame.pack(fill=tk.X, padx=8, pady=5)
        
        # 垂直同步单选按钮
        sync_on_radio = ttk.Radiobutton(sync_frame, text="开", variable=self.sync_var, value=1)
        sync_on_radio.pack(side=tk.LEFT, padx=10, pady=8)
        
        sync_off_radio = ttk.Radiobutton(sync_frame, text="关", variable=self.sync_var, value=0)
        sync_off_radio.pack(side=tk.LEFT, padx=10, pady=8)
        
        # === 底部按钮和标志区域 ===
        bottom_frame = ttk.Frame(self.root)
        bottom_frame.pack(fill=tk.X, side=tk.BOTTOM, padx=2, pady=2)
        
        # NVIDIA标志区域 (用一个简单的标签代替)
        nvidia_label = ttk.Label(bottom_frame, text="NVIDIA")
        nvidia_label.pack(side=tk.LEFT, padx=5)
        
        # 右侧按钮
        right_buttons_frame = ttk.Frame(bottom_frame)
        right_buttons_frame.pack(side=tk.RIGHT, padx=5)
        
        export_button = ttk.Button(right_buttons_frame, text="验证信息导出")
        export_button.grid(row=0, column=0, padx=1, pady=1)
        
        import_button = ttk.Button(right_buttons_frame, text="验证信息导入")
        import_button.grid(row=0, column=1, padx=1, pady=1)
        
        ok_button = ttk.Button(right_buttons_frame, text="确定", command=self.save_config)
        ok_button.grid(row=1, column=0, padx=1, pady=1)
        
        exit_button = ttk.Button(right_buttons_frame, text="确定并退出", command=self.save_and_exit)
        exit_button.grid(row=1, column=1, padx=1, pady=1)
        
        close_button = ttk.Button(right_buttons_frame, text="关闭", command=self.root.destroy)
        close_button.grid(row=1, column=2, padx=1, pady=1)
        
        # 系统信息选项卡内容
        info_frame = ttk.Frame(system_info_tab, padding=5)
        info_frame.pack(fill=tk.BOTH, expand=True)
        
        # 系统信息字段
        author_frame = ttk.Frame(info_frame)
        author_frame.pack(fill=tk.X, pady=2)
        ttk.Label(author_frame, text="作者：").pack(side=tk.LEFT)
        ttk.Label(author_frame, text="betesla").pack(side=tk.LEFT)
        
        company_frame = ttk.Frame(info_frame)
        company_frame.pack(fill=tk.X, pady=2)
        ttk.Label(company_frame, text="公司：").pack(side=tk.LEFT)
        ttk.Label(company_frame, text="下山硬月科技").pack(side=tk.LEFT)
        
        date_frame = ttk.Frame(info_frame)
        date_frame.pack(fill=tk.X, pady=2)
        ttk.Label(date_frame, text="日期：").pack(side=tk.LEFT)
        ttk.Label(date_frame, text="2025年5月9日").pack(side=tk.LEFT)
        
        qq_frame = ttk.Frame(info_frame)
        qq_frame.pack(fill=tk.X, pady=2)
        ttk.Label(qq_frame, text="Q群：").pack(side=tk.LEFT)
        ttk.Label(qq_frame, text="729310934").pack(side=tk.LEFT)
    
    def on_resolution_select(self, event):
        selected = self.resolution_var.get()
        # 解析选择的分辨率
        if "×" in selected:
            parts = selected.split("×")
            width = parts[0].strip()
            height = parts[1].strip()
            # 设置值
            self.width_var.set(width)
            self.height_var.set(height)
            # 同步到输入框
            self.width_entry.delete(0, tk.END)
            self.width_entry.insert(0, width)
            self.height_entry.delete(0, tk.END)
            self.height_entry.insert(0, height)
    
    def on_custom_resolution(self, event):
        # 手动输入分辨率时，自动更新下拉框显示为"自定义"
        try:
            width = int(self.width_var.get())
            height = int(self.height_var.get())
            res_text = f"{width} × {height}"
            if res_text not in self.resolution_list:
                self.resolution_var.set("自定义")
            else:
                self.resolution_var.set(res_text)
        except Exception:
            self.resolution_var.set("自定义")
    
    def write_hex_value(self, value, length=4):
        """将整数值转换为指定长度的十六进制字节串"""
        hex_str = format(value, f'0{length*2}x')
        byte_list = []
        for i in range(0, len(hex_str), 2):
            byte_list.append(int(hex_str[i:i+2], 16))
        
        # 按小端序排列
        byte_list.reverse()
        return bytes(byte_list)
    
    def read_hex_value(self, data, pattern):
        """从二进制数据中查找模式并读取其后的十六进制值"""
        match = re.search(pattern, data)
        if match:
            pos = match.end()
            # 读取4字节 (小端序)
            value_bytes = data[pos:pos+4]
            if len(value_bytes) == 4:
                # 转换为小端序整数
                value = int.from_bytes(value_bytes, byteorder='little')
                return value, pos
        return None, -1
    
    def load_config(self):
        try:
            config = {
                'fullscreen': 0,
                'widescreen': 0,
                'width': 800,
                'height': 600,
                'sync': 1
            }
            
            if os.path.exists(self.config_path):
                with open(self.config_path, 'rb') as f:
                    self.original_data = f.read()
                    
                    # 读取各个配置项的值
                    fullscreen_val, _ = self.read_hex_value(self.original_data, b'fullscreen')
                    if fullscreen_val is not None:
                        config['fullscreen'] = fullscreen_val
                    
                    height_val, _ = self.read_hex_value(self.original_data, b'height')
                    if height_val is not None:
                        config['height'] = height_val
                    
                    sync_val, _ = self.read_hex_value(self.original_data, b'sync')
                    if sync_val is not None:
                        config['sync'] = sync_val
                    
                    widescreen_val, _ = self.read_hex_value(self.original_data, b'widescreen')
                    if widescreen_val is not None:
                        config['widescreen'] = widescreen_val
                    
                    width_val, _ = self.read_hex_value(self.original_data, b'width')
                    if width_val is not None:
                        config['width'] = width_val
            
            # 更新界面值
            self.width_var.set(config['width'])
            self.height_var.set(config['height'])
            self.fullscreen_var.set(config['fullscreen'])
            self.sync_var.set(config['sync'])
            self.widescreen_var.set(config['widescreen'])
            
            # 更新分辨率下拉框
            resolution_text = f"{config['width']} × {config['height']}"
            
            # 检查当前分辨率是否在列表中
            if resolution_text in self.resolution_list:
                self.resolution_var.set(resolution_text)
            else:
                # 不在列表中，添加到下拉框选项
                self.resolution_list.append(resolution_text)
                self.res_combo.configure(values=self.resolution_list)
                self.resolution_var.set(resolution_text)
                
        except Exception as e:
            messagebox.showerror("加载错误", f"无法加载配置文件: {str(e)}")
    
    def save_config(self):
        try:
            # 如果没有原始数据，则创建一个新的简单配置
            if not self.original_data:
                # 创建最基本的配置文件
                self.original_data = (
                    b'\x00' * 0x18 +  # 24字节的头部
                    b'fullscreen\x00\x00\x00\x00' +
                    b'height\x00\x00\x00\x00' +
                    b'sync\x00\x00\x00\x00' +
                    b'widescreen\x00\x00\x00\x00' +
                    b'width\x00\x00\x00\x00'
                )
            
            # 创建修改后的数据副本
            new_data = bytearray(self.original_data)
            
            # 配置项列表
            config_items = [
                (b'fullscreen', self.fullscreen_var.get()),
                (b'height', self.height_var.get()),
                (b'sync', self.sync_var.get()),
                (b'widescreen', self.widescreen_var.get()),
                (b'width', self.width_var.get())
            ]
            
            # 逐个替换配置值
            for key, value in config_items:
                # 查找键值位置
                _, pos = self.read_hex_value(self.original_data, key)
                if pos > 0:
                    # 生成新的值
                    new_value = self.write_hex_value(value)
                    # 替换4个字节
                    for i in range(4):
                        if pos + i < len(new_data):
                            new_data[pos + i] = new_value[i]
            
            # 写回文件
            with open(self.config_path, 'wb') as f:
                f.write(new_data)
            
            messagebox.showinfo("成功", "配置已成功保存！")
        except Exception as e:
            messagebox.showerror("保存错误", f"无法保存配置文件: {str(e)}")
    
    def save_and_exit(self):
        """保存配置并退出程序"""
        self.save_config()
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = ConfigEditor(root)
    root.mainloop() 